package com.lry.pda.bottom.c.backend.executor;

import com.lry.pda.bottom.c.backend.*;
import com.lry.pda.bottom.c.backend.code.CodeKey;
import com.lry.pda.bottom.c.backend.code.CodeNode;
import com.lry.pda.bottom.c.backend.code.CodeTreeBuilder;
import com.lry.pda.bottom.c.backend.type.Declarator;
import com.lry.pda.bottom.c.backend.type.Symbol;
import com.lry.pda.bottom.c.frontend.Grammar;
import com.sun.org.apache.bcel.internal.classfile.Code;

import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;

public class UnaryExecutor extends BaseExecutor{

    private void setPointerValue(CodeNode root, Symbol symbol, int index) {
        MemoryHeap memHeap = MemoryHeap.getSelf();
        int addr = (Integer)symbol.getValue();
        Map.Entry<Integer, byte[]> entry = memHeap.getMem(addr);
        byte[] content = entry.getValue();
        index = index*symbol.getByteSize();
        //取值
        if (symbol.getByteSize() == 1) {
            root.setAttr(CodeKey.VALUE, content[index]);
        } else {
            ByteBuffer buffer = ByteBuffer.allocate(4);
            buffer.put(content, index, 4);
            buffer.flip();//切换到读模式
            root.setAttr(CodeKey.VALUE, buffer.getInt());
        }
    }

    private void setPointerValue2(CodeNode root, Symbol symbol, int offset) {
        MemoryHeap memHeap = MemoryHeap.getSelf();
        int addr = (Integer)symbol.getValue();
        Map.Entry<Integer, byte[]> entry = memHeap.getMem(addr);
        byte[] content = entry.getValue();
        //取值
        if (symbol.getByteSize() == 1) {
            root.setAttr(CodeKey.VALUE, content[offset]);
        } else {
            ByteBuffer buffer = ByteBuffer.allocate(4);
            buffer.put(content, offset, 4);
            buffer.flip();//切换到读模式
            root.setAttr(CodeKey.VALUE, buffer.getInt());
        }
    }

    @Override
    public void execute(CodeNode root) {
        executeChildren(root);

        int production = (Integer)root.getAttr(CodeKey.PRODUCTION);
        String text ;
        Symbol symbol;
        CodeNode child;

        if(production== Grammar.Number_TO_Unary){
            text = (String)root.getAttr(CodeKey.TEXT);
            boolean isFloat = text.indexOf('.') != -1;
            if (isFloat) {
                root.setAttr(CodeKey.VALUE, Float.valueOf(text));
            } else {
                root.setAttr(CodeKey.VALUE, Integer.valueOf(text));
            }
        }
        else if(production == Grammar.Name_TO_Unary){
            symbol = (Symbol)root.getAttr(CodeKey.SYMBOL);
            if(null!=symbol){
                Declarator declarator = symbol.getDeclarator(Declarator.ARRAY);
                if(null!=declarator){
                    root.setAttr(CodeKey.VALUE, declarator.getElements());
                    root.setAttr(CodeKey.TEXT, symbol.getName());
                }else{
                    root.setAttr(CodeKey.VALUE, symbol.getValue());
                    root.setAttr(CodeKey.TEXT, symbol.getName());
                }
            }
        }else if(production==Grammar.STAR_UNARY_TO_UNARY){

            child = root.getChildren().get(0);
            symbol = (Symbol)child.getAttr(CodeKey.SYMBOL);

            int addr = (Integer)child.getAttr(CodeKey.VALUE); //get mem addr

            MemoryHeap memHeap = MemoryHeap.getSelf();
            Map.Entry<Integer, byte[]> entry = memHeap.getMem(addr);
            if(null==entry){
                System.err.println(String.format("野指针%s试图访问不存在的内存地址",symbol.getName()));
                System.exit(1);
            }

            //获取值
            int offset = addr - entry.getKey();
            setPointerValue2(root,symbol,offset);

            //赋值
            DirectMemValueSetter directMemValueSetter = new DirectMemValueSetter(addr,symbol.getByteSize());
            root.setAttr(CodeKey.SYMBOL, directMemValueSetter);
        }
        else if(production == Grammar.String_TO_Unary){
            text = (String)root.getAttr(CodeKey.TEXT);
            root.setAttr(CodeKey.VALUE, text);
        }else if(production==Grammar.FALSE_TO_Unary){
            root.setAttr(CodeKey.VALUE, false);
        }else if(production==Grammar.TRUE_TO_Unary){
            root.setAttr(CodeKey.VALUE, true);
        }
        else if(production == Grammar.Unary_LB_Expr_RB_TO_Unary) {
            child = root.getChildren().get(0);
            symbol = (Symbol)child.getAttr(CodeKey.SYMBOL);
            root.setAttr(CodeKey.TEXT, symbol.getName());
            //取数组idx值
            child = root.getChildren().get(1);
            int index = (Integer)child.getAttr(CodeKey.VALUE);

            Declarator declarator = symbol.getDeclarator(Declarator.ARRAY);
            if(declarator!=null){
                //取值
                Object val = declarator.getElement(index);
                root.setAttr(CodeKey.VALUE, val);
                //组装赋值setter
                ArrayValueSetter setter = new ArrayValueSetter(symbol, index);
                root.setAttr(CodeKey.SYMBOL, setter);
            }

            Declarator pointer = symbol.getDeclarator(Declarator.POINTER);
            if(null!=pointer){
                setPointerValue(root, symbol, index);
                //create a PointerSetter
                PointerValueSetter pv = new PointerValueSetter(symbol, index);
                root.setAttr(CodeKey.SYMBOL, pv);
                root.setAttr(CodeKey.TEXT, symbol.getName());
            }
        }
        //i++,++i
        else if(production == Grammar.UNARY_INCOP_TO_UNARY
        ||production==Grammar.INCOP_UNARY_TO_UNARY){
            child = root.getChildren().get(0);
            symbol = (Symbol)child.getAttr(CodeKey.SYMBOL);
            int val = (int) symbol.getValue();
            symbol.setValue(val+1);
            if(production == Grammar.UNARY_INCOP_TO_UNARY){
                root.setAttr(CodeKey.VALUE,val);
            }else{
                root.setAttr(CodeKey.VALUE,val+1);
            }
        }
        //i--,--i
        else if(production == Grammar.UNARY_DECOP_TO_UNARY
                ||production==Grammar.DECOP_UNARY_TO_UNARY){
            child = root.getChildren().get(0);
            symbol = (Symbol)child.getAttr(CodeKey.SYMBOL);
            int val = (int) symbol.getValue();
            symbol.setValue(val-1);
            if(production == Grammar.UNARY_DECOP_TO_UNARY){
                root.setAttr(CodeKey.VALUE,val);
            }else{
                root.setAttr(CodeKey.VALUE,val-1);
            }
        }
        //b=-a
        else if(production==Grammar.MINUS_UNARY_TO_UNARY){
            child = root.getChildren().get(0);
            symbol = (Symbol)child.getAttr(CodeKey.SYMBOL);
            int val = (int) symbol.getValue();
            root.setAttr(CodeKey.VALUE,-val);
        }
        //a=*b; 指针
        else if(production==Grammar.STAR_UNARY_TO_UNARY){

        }
        //a=(1+2)
        else if(production==Grammar.LP_EXPR_RP_TO_UNARY){
            executeChild(root,0);
            copyChild(root,root.getChildren().get(0));
        }else if(production==Grammar.UNARY_COMPOUND_ASSIGN_UNARY_TO_UNARY){
            symbol = (Symbol)root.getChildren().get(0).getAttr(CodeKey.SYMBOL);
            int val = (int) symbol.getValue();

            String operator = (String)root.getChildren().get(1).getAttr(CodeKey.TEXT);

            int val2 = (Integer)root.getChildren().get(2).getAttr(CodeKey.VALUE);

            if("+=".equals(operator)){
                symbol.setValue(val+val2);
            }else if("-=".equals(operator)){
                symbol.setValue(val-val2);
            }else if("*=".equals(operator)){
                symbol.setValue(val*val2);
            }else if("/=".equals(operator)){
                symbol.setValue(val/val2);
            }else if("^=".equals(operator)){
                symbol.setValue(val^val2);
            }else if("&=".equals(operator)){
                symbol.setValue(val&val2);
            }else if("|=".equals(operator)){
                symbol.setValue(val|val2);
            }
        }
        //调用无参函数
        else if(production==Grammar.UNARY_LP_RP_TO_UNARY
        ||production==Grammar.UNARY_LP_ARGS_RP_TO_UNARY){
            //先获得函数名
            String funcName = (String)root.getChildren().get(0).getAttr(CodeKey.TEXT);

            //设置函数参数
            if(production==Grammar.UNARY_LP_ARGS_RP_TO_UNARY){
                CodeNode argsNode = root.getChildren().get(1);
                List<Object> argList = (List<Object>)argsNode.getAttr(CodeKey.VALUE);
                FuncArgHelper.getSelf().setFuncArgList(argList);
            }
            Object returnVal = null;
            //找到函数执行树头节点
            CodeNode func = CodeTreeBuilder.getSelf().funcMap.get(funcName);
            if (func != null) {
                Executor executor = ExecutorFactory.getExecutor(func);
                executor.execute(func);
                returnVal = func.getAttr(CodeKey.VALUE);

            }else{
                CLibCall cLibCall = CLibCall.getSelf();
                if(cLibCall.isAPICall(funcName)){
                    Object obj = cLibCall.invokeAPI(funcName);
                    returnVal = obj;
                    root.setAttr(CodeKey.VALUE, obj);
                }
            }
            if (returnVal != null) {
                System.out.println("function call with name " + funcName + " has return value that is " + returnVal.toString());
                root.setAttr(CodeKey.VALUE, returnVal);
            }
        }
    }
}
